package handler

import (
	"encoding/json"
	"strconv"
	"time"
	"web_framework/model"
	"web_framework/pkg/constvar"
	"web_framework/pkg/e"
	"web_framework/service"
	"web_framework/storage"
)

//外接设备插拔通知
type GetStorageParHandle struct {
}

func (getStorageParHandle GetStorageParHandle) handleMsg(data model.Request, sn string) (result model.Response) {
	if data.Mtype == constvar.MTypeGetStorageParResponse {

		noticeType := storage.StorageOutNotice
		var dPath = make(map[string]interface{})
		if data.Data.Storages != nil {
			noticeType = storage.StorageOnNotice
			storagePartition := make(map[string]model.ResponsePartition)
			var index int
			var maxAvailableSize int64
			var defaultPathKey string
			for _, sto := range data.Data.Storages {
				for _, partition := range sto.Partitions {
					index++
					var mapKey string
					// uuid不为空时使用sn和uuid唯一确定一个分区；uuid为空时使用sn和seq唯一确定一个分区
					mapKey = e.Md5Str(sto.Sn + partition.UUID + strconv.Itoa(partition.Seq))
					parData := model.ResponsePartition{
						Sn:            sto.Sn,
						UUID:          partition.UUID,
						Seq:           partition.Seq,
						TotalSize:     e.StorageSpaceConversion(partition.TotalSize),
						AvailableSize: e.StorageSpaceConversion(partition.AvailableSize),
						DevName:       "分区" + strconv.Itoa(index),
						Path:          partition.Path,
						Index:         index,
					}
					storagePartition[mapKey] = parData
					//可用存储空间排序
					if index == 1 {
						defaultPathKey = mapKey
						maxAvailableSize = partition.AvailableSize
					} else if partition.AvailableSize >= maxAvailableSize {
						defaultPathKey = mapKey
						maxAvailableSize = partition.AvailableSize
					}
				}
			}

			var mapKeySlice = make([]string, 0)
			for key, _ := range storagePartition {
				mapKeySlice = append(mapKeySlice, key)
			}
			partition, _ := json.Marshal(mapKeySlice)
			partitionCacheKey := constvar.RouterRedisPrefix + sn + storage.RedisStoragePartitionKey
			var isWriteDefaultPath = false // 写默认分区 默认不写
			if !storage.RedisExists(partitionCacheKey) {
				isWriteDefaultPath = true
			}

			if storage.RedisExists(partitionCacheKey) {
				partitionCache, _ := storage.RedisGet(partitionCacheKey)
				//判断外接存储是否有变化
				if partitionCache != string(partition) {
					isWriteDefaultPath = true
				}
			}

			// 默认分区
			if isWriteDefaultPath {
				// 缓存分区标识信息，判断外接存储是否变化
				_, setParErr := storage.RedisSet(partitionCacheKey, partition, -1)
				if setParErr != nil {
					e.Log("Info", setParErr.Error()+"外接存储设备分区信息缓存失败")
					return ReturnErr(data.Mid, constvar.MTypeGetStorageParResponse, setParErr.Error()+"外接存储设备分区信息缓存失败")
				}
				//缓存分区详情
				jsonStr, _ := json.Marshal(storagePartition)
				partitionInfoCacheKey := constvar.RouterRedisPrefix + sn + storage.RedisStoragePartitionInfoKey
				_, cacheErr := storage.RedisSet(partitionInfoCacheKey, jsonStr, -1)
				if cacheErr != nil {
					e.Log("Info", "外接存储设备分区信息缓存失败", cacheErr.Error())
					return ReturnErr(data.Mid, constvar.MTypeGetStorageParResponse, cacheErr.Error()+"外接存储设备分区信息缓存失败")
				}
				// 先拿到默认分区数据  准备更新到redis
				dPath["sn"] = storagePartition[defaultPathKey].Sn
				dPath["uuid"] = storagePartition[defaultPathKey].UUID
				dPath["seq"] = strconv.Itoa(storagePartition[defaultPathKey].Seq)
				dPath["path"] = storagePartition[defaultPathKey].Path
				partitionDPathCacheKey := constvar.RouterRedisPrefix + sn + storage.RedisStoragePartitionDPathKey
				_, dPathCacheErr := storage.RedisHSet(partitionDPathCacheKey, dPath, -1)
				if dPathCacheErr != nil {
					e.Log("Info", "外接存储设备默认下载目录信息缓存失败", dPathCacheErr.Error())
					return ReturnErr(data.Mid, constvar.MTypeGetStorageParResponse, dPathCacheErr.Error()+"外接存储设备默认下载目录信息缓存失败")
				}

				//设置默认分区，向下载模块推送
				requestMid, _ := service.GenMid(sn)
				seqInt,_ := strconv.Atoi(dPath["seq"].(string))
				var wsPushData = model.Request{
					Mid:   requestMid,
					Mtype: constvar.MTypeSetPartitionRequest,
					Time:  time.Now().Unix(),
					Data: &model.RequestData{
						Sn:   dPath["sn"].(string),
						UUID: dPath["uuid"].(string),
						Seq:  seqInt,
					},
				}
				conn := RouterMaps[sn]
				Route(wsPushData, conn)
			}
		}

		//插拔通知
		tokenSlice, getTokenErr := service.GetUserTokenBySn(sn)
		if getTokenErr != nil {
			e.Log("Info", "获取用户token失败：", getTokenErr.Error())
			return ReturnErr(data.Mid, constvar.MTypeGetStorageParResponse, getTokenErr.Error()+",获取用户token失败")
		}

		mid, _ := service.GenMid(sn)
		var requestData = model.Request{
			Mid:   mid,
			Mtype: constvar.MTypeGetStorageParResponse,
			Data: &model.RequestData{
				NoticeType: noticeType,
				Sn:         sn,
			},
		}
		//获取推送的消息体
		for _, clientToken := range tokenSlice {
			conn, ok := RouterMaps[clientToken]
			if ok {
				Route(requestData, conn)
			}
		}

		return model.Response{
			Mid:    data.Mid,
			Mtype:  constvar.MTypeRouterStorageOutNoticeResponse,
			Status: constvar.StatusOk,
			Data:   nil,
		}
	}
	e.Log("Info", "mType错误：1105")
	return ReturnErr(data.Mid, constvar.MTypeGetStorageParResponse, "mtype错误")
}
